package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.common.cache.GmallCache;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.constant.MqConst;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.*;
import com.atguigu.gmall.product.mapper.SkuSaleAttrValueMapper;
import com.atguigu.gmall.product.service.ManageService;
import com.atguigu.gmall.service.RabbitService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service
@Slf4j
@Transactional //类头上或方法头上
public class ManageServiceImpl implements ManageService {

    @Autowired
    private BaseCategory1Mapper baseCategory1Mapper;
    @Autowired
    private BaseCategory2Mapper baseCategory2Mapper;
    @Autowired
    private BaseCategory3Mapper baseCategory3Mapper;
    @Autowired
    private BaseAttrInfoMapper baseAttrInfoMapper;
    @Autowired
    private BaseAttrValueMapper baseAttrValueMapper;
    @Autowired
    private BaseTrademarkMapper baseTrademarkMapper;
    @Autowired
    private SpuInfoMapper spuInfoMapper;
    @Autowired
    private BaseSaleAttrMapper baseSaleAttrMapper;
    //查询一级分类
    @Override
    public List<BaseCategory1> getCategory1() {
        return baseCategory1Mapper.selectList(null);
    }

    //获取二级分类
    @Override
    public List<BaseCategory2> getCategory2(Long category1Id) {
        return baseCategory2Mapper.
                selectList(
                        new QueryWrapper<BaseCategory2>()
                                .eq("category1_id",category1Id));
    }
    //获取三级分类

    @Override
    public List<BaseCategory3> getCategory3(Long category2Id) {
        return baseCategory3Mapper.
                selectList(
                        new QueryWrapper<BaseCategory3>()
                                .eq("category2_id",category2Id));
    }

    //查询平台属性集合
    @Override
    public List<BaseAttrInfo> getBaseAttrInfo(Long category1Id, Long category2Id, Long category3Id) {
        return baseAttrInfoMapper.getBaseAttrInfo(category1Id,category2Id,category3Id);
    }

    //添加平台属性
    @Override
    public void saveAttrInfo(BaseAttrInfo baseAttrInfo) {
        //保存平台属性表 1   主键  Mybatis Plus 默认就有
        baseAttrInfoMapper.insert(baseAttrInfo);
        //保存平台属性值表 N  外键
        baseAttrInfo.getAttrValueList().forEach(value -> {
            // 外键
            value.setAttrId(baseAttrInfo.getId());
            baseAttrValueMapper.insert(value);
        });
    }

    //品牌分页查询
    @Override
    public IPage baseTrademark(Integer page, Integer limit) {
        //总条数
       return baseTrademarkMapper.selectPage(new Page(page, limit), null);
    }

    //商品SPU分页查询
    @Override
    public IPage productPage(Integer page, Integer limit, Long category3Id) {
        return spuInfoMapper.selectPage(new Page(page, limit),
                new QueryWrapper<SpuInfo>().eq("category3_id",category3Id));
    }


    //商品添加之品牌下拉框
    @Override
    public List<BaseTrademark> getTrademarkList() {
        return baseTrademarkMapper.selectList(null);
    }

    //  // 获取销售属性列表
    @Override
    public List<BaseSaleAttr> baseSaleAttrList() {
        return baseSaleAttrMapper.selectList(null);
    }


    @Autowired
    private SpuImageMapper spuImageMapper;
    @Autowired
    private SpuSaleAttrMapper spuSaleAttrMapper;
    @Autowired
    private SpuSaleAttrValueMapper spuSaleAttrValueMapper;

    //spu保存  transactional  start  前置    select    后置  返回值   commit  异常  rollback
    @Override
    public void saveSpuInfo(SpuInfo spuInfo) {
        //1:保存spuInfo
        spuInfoMapper.insert(spuInfo);
        log.info("保存spuInfo表已经成功了,ID是{}",spuInfo.getId());//Spring Aop  SpringBoot
        //2:保存图片
        List<SpuImage> spuImageList = spuInfo.getSpuImageList();
        if(null != spuImageList && spuImageList.size() > 0){
            spuImageList.forEach(spuImage -> {
                //外键
                spuImage.setSpuId(spuInfo.getId());
                spuImageMapper.insert(spuImage);
            });
        }
        //3:保存销售属性
        spuInfo.getSpuSaleAttrList().forEach(spuSaleAttr -> {
            spuSaleAttr.setSpuId(spuInfo.getId());
            spuSaleAttrMapper.insert(spuSaleAttr);
            //4:保存销售属性值表
            spuSaleAttr.getSpuSaleAttrValueList().forEach(spuSaleAttrValue -> {
                //外键
                spuSaleAttrValue.setSpuId(spuInfo.getId());
                //冗余字段 销售属性名称
                spuSaleAttrValue.setSaleAttrName(spuSaleAttr.getSaleAttrName());
                spuSaleAttrValueMapper.insert(spuSaleAttrValue);
            });

        });

    }


    @Autowired
    private SkuInfoMapper skuInfoMapper;
    @Autowired
    private SkuImageMapper skuImageMapper;
    @Autowired
    private SkuAttrValueMapper skuAttrValueMapper;
    @Autowired
    private SkuSaleAttrValueMapper skuSaleAttrValueMapper;
    //查询Sku分页对象
    @Override
    public IPage list(Integer page, Integer limit) {
        return skuInfoMapper.selectPage(new Page(page,limit),null);
    }

    //根据spuId 查询所有图片
    @Override
    public List<SpuImage> spuImageList(Long spuId) {
        return spuImageMapper.selectList(new QueryWrapper<SpuImage>()
                .eq("spu_id",spuId));
    }
    //查询销售属性及值
    @Override
    public List<SpuSaleAttr> spuSaleAttrList(Long spuId) {
        return spuSaleAttrMapper.getSpuSaleAttrList(spuId);
    }

    //添加Sku
    @Override
    public void saveSkuInfo(SkuInfo skuInfo) {
        //1:sku_info
        skuInfoMapper.insert(skuInfo);
        //2:sku_image
        skuInfo.getSkuImageList().forEach(skuImage -> {
            skuImage.setSkuId(skuInfo.getId());
            skuImageMapper.insert(skuImage);
        });
        //3:sku_attr_value
        skuInfo.getSkuAttrValueList().forEach(skuAttrValue -> {
            skuAttrValue.setSkuId(skuInfo.getId());
            skuAttrValueMapper.insert(skuAttrValue);
        });
        //4:sku_sale_attr_value
        skuInfo.getSkuSaleAttrValueList().forEach(skuSaleAttrValue -> {
            skuSaleAttrValue.setSkuId(skuInfo.getId());
            skuSaleAttrValue.setSpuId(skuInfo.getSpuId());
            skuSaleAttrValueMapper.insert(skuSaleAttrValue);
        });

    }

    @Autowired
    private RabbitService rabbitService;
    //上架
    @Override
    public void onSale(Long skuId) {

        //1:更新  update
        SkuInfo skuInfo = new SkuInfo();
        skuInfo.setIsSale(1);//硬编码问题
        skuInfo.setId(skuId);//Mybatis-plus
        skuInfoMapper.updateById(skuInfo);//update sku_info set is_sale = 1 where id = 1

        //发消息
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_GOODS,
                MqConst.ROUTING_GOODS_UPPER,skuId);

    }

    //下架
    @Override
    public void cancelSale(Long skuId) {
        //1:更新  update
        SkuInfo skuInfo = new SkuInfo();
        skuInfo.setIsSale(0);
        skuInfo.setId(skuId);//Mybatis-plus
        skuInfoMapper.updateById(skuInfo);//update sku_info set is_sale = 1 where id = 1

        //发消息
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_GOODS,
                MqConst.ROUTING_GOODS_LOWER,skuId);
    }
   // 根据skuId查询SkuInfo对象 （名称 描述 价格 三级分类ID）默认图片
    //根据skuId查询SkuImage集合
    @Override
    @GmallCache(prefix = RedisConst.SKULOCK_PREFIX)
    public SkuInfo getSkuInfo(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        if(null != skuInfo){
            //根据skuId查询SkuImage集合
            skuInfo.setSkuImageList(skuImageMapper.
                    selectList(new QueryWrapper<SkuImage>().eq("sku_id",skuId)));
        }
        return skuInfo;
    }

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;


  /* @Override
   public SkuInfo getSkuInfo(Long skuId) {//1
       //缓存的Key 命名规范
       String cacheKey = "sku:" + skuId + ":info";
        //1:先从缓存中获取
       SkuInfo skuInfo = (SkuInfo) redisTemplate.opsForValue().get(cacheKey);
       if(null != skuInfo){
           //2:有 直接返回
           return skuInfo;
       }
       //3:没有  上锁
       String cacheLock = "getSkuInfo:" + skuId;
       RLock lock = redissonClient.getLock(cacheLock);

            //参数1： 过时不候 等待获取锁的时间
            //参数2： 一旦获取到锁 这个锁的过期时间
       boolean tryLock = false;//可重入锁  过时不候
       try {
           tryLock = lock.tryLock(1, 3, TimeUnit.SECONDS);
           if(tryLock) {
               try {
                   // 从数据库中查询 86ms
                   skuInfo = skuInfoMapper.selectById(skuId);
                   //4:判断此商品在数据库中是否存在
                   if (null != skuInfo) {
                       //根据skuId查询SkuImage集合
                       skuInfo.setSkuImageList(skuImageMapper.
                               selectList(new QueryWrapper<SkuImage>().eq("sku_id", skuId)));
                       //再保存缓存中一份 直接返回
                       redisTemplate.opsForValue().set(cacheKey, skuInfo,
                               RedisConst.SKUKEY_TIMEOUT + new Random().nextInt(300),
                               TimeUnit.SECONDS);
                   } else {
                       skuInfo = new SkuInfo();
                       redisTemplate.opsForValue().set(cacheKey, skuInfo, 3, TimeUnit.MINUTES);
                   }
               } catch (Exception e) {
                   //e.printStackTrace();
                   //日志  记录报错信息 定位错误
               } finally {
                   lock.unlock();
               }
           }else{
               Thread.sleep(1000);
               return (SkuInfo) redisTemplate.opsForValue().get(cacheKey);
           }
       } catch (InterruptedException e) {
           //e.printStackTrace();
       }
       return skuInfo;
   }*/

    @Autowired
    private BaseCategoryViewMapper baseCategoryViewMapper;
    //根据三级分类ID查询一二三级分类（的单个名称）
    @Override
    public BaseCategoryView getCategoryView(Long id) {

        return baseCategoryViewMapper.selectById(id);
    }

    //根据skuId 查询销售属性集合及对应的销售属性值集合
    @Override
    public List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(Long skuId, Long spuId) {
        return spuSaleAttrMapper.getSpuSaleAttrListCheckBySku(skuId,spuId);
    }

    //   要求单独查询价格时时更新（Mysql)(不能使用缓存）
    @Override
    public BigDecimal getSkuPrice(Long skuId)  {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        if(null != skuInfo){//  预期异常   //运行时异常
            return skuInfo.getPrice();
        }
       return null;
    }

    //根据spuId查询   颜色与销售属性值组合对应的skuId
    @Override
    public List<Map> getSkuValueIdsMap(Long spuId) {
        return skuSaleAttrValueMapper.getSkuValueIdsMap(spuId);
    }

    //查询首页一二三级分类的数据
    @Override
    public List<Map> getCategoryList() {
        List<BaseCategoryView> baseCategoryViewList =
                baseCategoryViewMapper.selectList(null);//1099
        //逻辑开发 Lambda
        List<Map> listMap = new ArrayList<>();

        // Map1  K:Long 一级分类ID  V：List<BaseCategoryView> 长度 60
        // Map2  K:Long 一级分类ID  V：List<BaseCategoryView> 长度 25
        Map<Long, List<BaseCategoryView>> baseCategoryMap = baseCategoryViewList.stream().collect(
                Collectors.groupingBy(BaseCategoryView::getCategory1Id));

        //遍历
        int index = 1;
        for (Map.Entry<Long, List<BaseCategoryView>> category1entry :
                baseCategoryMap.entrySet()) {
            //一级分类
            Map map1 = new HashMap();
            map1.put("index",index++);
            map1.put("categoryId",category1entry.getKey());
            map1.put("categoryName",
                    category1entry.getValue().get(0).getCategory1Name());
            //一级分类子集合是二级分类的集合
            List<Map> listMap2 = new ArrayList<>();

            //Map1 K:Long 二级分类的ID  V：List<BaseCategoryView> 4个
            Map<Long, List<BaseCategoryView>> baseCategory2Map =
                    category1entry.getValue().stream().
                    collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));
            for (Map.Entry<Long, List<BaseCategoryView>> category2entry :
                    baseCategory2Map.entrySet()) {
                Map map2 = new HashMap();
                map2.put("categoryId",category2entry.getKey());
                map2.put("categoryName",
                        category2entry.getValue().get(0).getCategory2Name());
                //
                List<BaseCategoryView> category3List = category2entry.getValue();
                List<Map> listMap3 = new ArrayList<>();
                for (BaseCategoryView baseCategoryView : category3List) {
                    Map map3 = new HashMap();
                    map3.put("categoryId",baseCategoryView.getCategory3Id());
                    map3.put("categoryName",baseCategoryView.getCategory3Name());
                    listMap3.add(map3);
                }
                map2.put("categoryChild",listMap3);
                listMap2.add(map2);
            }
            map1.put("categoryChild",listMap2);
            listMap.add(map1);
        }
        return listMap;
    }

    //根据ID查询一个品牌
    @Override
    public BaseTrademark getTrademark(Long tmId) {
        return baseTrademarkMapper.selectById(tmId);
    }


    /*   根据skuId    一条Sql语句
   // 查询 关联的平台属性及属性值集合
   // 并根据平台属性ID查询名称
   // 根据平台属性值ID查询名称*/
    @Override
    public List<SkuAttrValue> getBaseAttrInfoAndValue(Long skuId) {
        return skuAttrValueMapper.getBaseAttrInfoAndValue(skuId);
    }
}
